#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <stdio.h>
void WStringConcat(WCHAR* dest, WCHAR* add)
{
	int i = 0;
	for(; dest[i] != 0; i++ )
	{
	}
	int j = 0;
	for(; add[j] != 0; j++ )
	{
		dest[i + j] = add[j];

	}
	dest[i + j] = 0;

}
void WStringToString(WCHAR* src, char * dest)
{
	int i = 0;

	for(; src[i] != 0; i++ )
	{
		dest[i] = src[i];
	}
	dest[i] = 0;
}

void StringToWString(char* src, WCHAR * dest)
{
	int i = 0;

	for(; src[i] != 0; i++ )
	{
		dest[i] = src[i];
	}
	dest[i] = 0;
}
//--------------------------------------------------------------------------------------
// Helper for compiling shaders with D3DX11
//--------------------------------------------------------------------------------------
HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut)
{
    HRESULT hr = S_OK;
	bool bForceRecompile = true;

    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
    // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
    // Setting this flag improves the shader debugging experience, but still allows 
    // the shaders to be optimized and to run exactly the way they will run in 
    // the release configuration of this program.
    dwShaderFlags |= D3DCOMPILE_DEBUG;
	dwShaderFlags |= D3D10_SHADER_DEBUG;
	
#endif
	FILE *fp;
	WCHAR wcachedFileName[255] = L"";
	WStringConcat(wcachedFileName, szFileName);
	WCHAR shaderType[20] = L"";
	StringToWString((char *)szEntryPoint, shaderType);
	WStringConcat(wcachedFileName, L".");
	WStringConcat(wcachedFileName, shaderType);
	WStringConcat(wcachedFileName, L"Cached");

	char cachedFileName[255] = "";
	WStringToString(wcachedFileName, cachedFileName);

	fopen_s(&fp, cachedFileName, "rb");
	if(fp == NULL || bForceRecompile)
	{
		if(fp != NULL)
			fclose(fp);
	

		ID3DBlob* pErrorBlob;
		hr = D3DX11CompileFromFile( szFileName, NULL, NULL, szEntryPoint, szShaderModel, 
			dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
		if( FAILED(hr) )
		{
			if( pErrorBlob != NULL )
				OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
			if( pErrorBlob ) pErrorBlob->Release();
			return hr;
		}
		if( pErrorBlob ) pErrorBlob->Release();

		errno_t err = fopen_s(&fp, cachedFileName, "wb+");
		fwrite((*ppBlobOut)->GetBufferPointer(), (*ppBlobOut)->GetBufferSize(), 1, fp);
		fclose(fp);
	}
	else
	{
		ID3DBlob* pBlob = NULL;
		fseek(fp, 0, 2);
		int fileLength = ftell(fp);
		fseek(fp, 0, 0);

		D3DCreateBlob(fileLength, &pBlob);
		void *pBlobVoid = pBlob->GetBufferPointer();
		fread(pBlobVoid, fileLength, 1, fp);
		fclose(fp);
		*ppBlobOut = pBlob;
	}

    return S_OK;
}
UINT GetSmallest4Multiple(UINT sz)
{
	UINT padding = 4 - (sz % 4);
	return sz + padding;
}